#coding=utf8
#-------------------------------------------------------------------------------
# Name:        ??1
# Purpose:
#
# Author:      weigun
#
# Created:     11-08-2011
# Copyright:   (c) weigun 2011
# Licence:     <your licence>
#-------------------------------------------------------------------------------
#!/usr/bin/env python
#import os
import re
import Log
import SvnClient
import os
#--import AppConfig
#--import Notify
class SvnConflictChecker():
    def __init__(self,queue_dict,conf):
        print 'SvnConflictChecker init'
        self.queue_dict= queue_dict
        self.conf = conf
        self.suffix = ['.xml','.lua',]

    def choose_revision(self,path,change_log_list,rev_num):
        '''选择需要检查的版本'''
        first_rev = -1
        second_rev = -1
        third_rev = -1 #--需要找到的3个版本
        find_count = 0 #--已经查找的版本数

        #print "now_rev",change_log_list[rev_num]['revision']

        the_new_file = change_log_list[rev_num]
        first_rev = the_new_file['revision'].number
        the_new_files_author = the_new_file['author']
        flag_rev = 1

        for i in range(rev_num-1,-1,-1):
            #print "choose_rev_i==",change_log_list[i]['revision']
            #print "flag_rev=",flag_rev
            if flag_rev == 3: #--已经找到3个版本了，退出
                return first_rev,second_rev,third_rev

            if find_count > 100: #--查找超过100个修改版本，退出
                return -1,-1,-1
            tmp_author = change_log_list[i]['author']
            #print "author=",tmp_author,the_new_files_author

            if flag_rev == 1:
                if tmp_author == the_new_files_author:
                    '''同一个作者修改，不予处理'''
                    return -1,-1,-1
                else:
                    second_rev = change_log_list[i]['revision'].number
                    flag_rev = 2
            elif flag_rev ==2:
                if tmp_author == the_new_files_author:
                    flag_rev = 3
                    third_rev = change_log_list[i]['revision'].number
                else:
                    find_count+=1

        if flag_rev <= 2:
            '''该文件只有两个以下的人修改的版本'''
            #print "only two rev"
            return -1,-1,-1

        #print "now rev:",first_rev,second_rev,third_rev
        return first_rev,second_rev,third_rev


    def find_change_num(self,mstring):
        '''寻找改变的行数，专用，不可通用'''
        mstring=mstring.split(',')
        return int(mstring[1].split(' ')[0]),int(mstring[2].split(' ')[0])


    def count_diff(self,diff_string):
            '''查找diff数量'''
            '''更改算法'''
            count_diff_num = 0
            tmp_diff_string = diff_string.split('\r\n')
            max_line = len(tmp_diff_string)
            context_iter = iter(tmp_diff_string) #--一个迭代器
            ignore_begin_flag = True
            for context in context_iter:
                if context.startswith('@@'):
                    ignore_begin_flag = False
                    old_num,new_num = self.find_change_num(context)
                    if old_num > new_num:
                        count_diff_num = count_diff_num + old_num - new_num
                else:
                    if ignore_begin_flag:
                        continue
                    if context.startswith("+"):
                        count_diff_num = count_diff_num + 1
            return count_diff_num

    def is_add_new_line(self,diff_summary):
        '''检测diff是否有新增行，返回true or false '''
        #found = re.findall('@@(.+)@@',diff_summary)
        found = self.get_diff_summary(diff_summary)
        if found:   #--[('2','7'),('2','7'),('12','17'),('12','17')]
            index = 0
            while index < len(found):
                if found[index][0] != found[index + 1][0] or found[index][1] != found[index + 1][1]:
                    return True
                index+=2
        return False

    def get_diff_summary(self,diff_string):
        '''得到从第几行开始，有几行发生改变,返回一个二维数组'''
        diff_summary = re.findall('(\d+),(\d+)',diff_string)
        return diff_summary

    def parse_diff(self,diff_context):
        '''解析diff的结果，返回一个字典'''
        '''
        diff_dict key are as follow:
            line :  --int
                {
                    add :   --string
                    del :   --string
                }
        '''
        if self.is_add_new_line(diff_context):#--有行数变化
            return  None
        print  "no line add!! GO ahead!"
        diff_dict = {}
        diff_context = diff_context.split('\r\n')
        max_line = len(diff_context)
        context_iter = iter(diff_context) #--一个迭代器
        ignore_begin_flag = True
        line_counter = -1 #--记录已经遍历了的行数
        '''
        diff有2种情况，1种就是
        -dfsf
        +asdadasd
        另一种是:
        -sdfsdfsdf
        -sdfvcxbvc445
        -45457464
        +bbbbbb
        +jkilo;8787
        +0000000bbb
        '''
        for context in context_iter:
            if context.startswith('@@'):
                change_num_del = 0
                change_num_add = 0 #--表明在一段diff中，已经修改了的行的数量
                line_counter = 0
                ignore_begin_flag = False
                diff_summary = self.get_diff_summary(context) #--[('2','7'),('2','7')]
                #print "change num:",diff_summary
            else:
                if ignore_begin_flag:
                    continue
                line_counter = line_counter + 1
                if context.startswith('+'):
                    #line_counter = line_counter + 1
                    change_num_add += 1
                    key = int(diff_summary[0][0]) + line_counter - change_num_del - 1

                    if not diff_dict.has_key(key):
                        print "这里单独增加了一行"
                    else:
                        diff_dict.setdefault(key,[])
                        diff_dict[key].append(context.replace('+','',1))
                elif (context.startswith('-')) and (not context.startswith('--')):
                    #line_counter = line_counter + 1
                    change_num_del += 1
                    key = int(diff_summary[0][0]) - 1 + line_counter - change_num_add
                    if not diff_dict.has_key(key):
                        diff_dict.setdefault(key,[])
                        diff_dict[key].append(context.replace('-','',1))
                    else:
                        print "可能那里弄错了"
        return diff_dict

    def file_filter(self,path):
        '''过滤器，返回true or false '''
        if os.path.splitext(path)[1] not in self.suffix:
            return False
        return True

    def add_log(self,msg):
        self.queue_dict['log_queue'].put(msg)

    def do_check(self):
        #--log = Log.Log()
        #--cfg_file = r'D:\Program Files\Maxthon3\Bin\config.ini'
        #--config = AppConfig.AppConfig(cfg_file,'utf-8-sig')
        #--notify = Notify.Notify(cfg_file)
        #target = r'https://test/' #--设置需要检查的根目录
        #target_list = ['folder'] #--设置检查的子目录
        print 'do_check running'
        for section in self.conf.sections():
            print 'in section:', type(section),section
            svn_url = self.conf.get_section_items(section).get('svnurl')
            print 'svn_url:',svn_url
            if not svn_url:
                continue
            target = svn_url
            user =  self.conf.get_section_items(section).get('user')
            passwd =  self.conf.get_section_items(section).get('passwd')
            svn = SvnClient.SvnClient(target,user,passwd,True)
            #--svn.set_logger(log)
            #print svn.get_info_by_num(target,32810).next()['repos_root_URL']
            print "Running......"
            #--允许进行diff的后缀名
        ##    for child_path in target_list:
        ##        target = svn.catfile(child_path)
        ##        print "path=",target
            tmp_dict = svn.get_yesterday_begin_and_end_revision(target)
            if 'begin' in tmp_dict:
                yesterday_begin_rev = tmp_dict['begin']
                yesterday_end_rev = tmp_dict['end']
                #print '@'*10,yesterday_begin_rev,yesterday_end_rev
                print 'found revision:',yesterday_begin_rev,yesterday_end_rev
                #--log.log('found revision:%s,%s'%(yesterday_begin_rev,yesterday_end_rev))
                self.add_log('found revision:%s,%s'%(yesterday_begin_rev,yesterday_end_rev))
                for yesterday_file_path in svn.changed_files(target,yesterday_begin_rev,yesterday_end_rev):
                    #--过滤器
                    if not self.file_filter(yesterday_file_path):
                        print yesterday_file_path,'not allow'
                        continue
                    yesterday_file_path = '/'.join((target,yesterday_file_path))
                    #yesterday_file_path = svn.catfile(yesterday_file_path)

                    #print "yesterday_file_path=",yesterday_file_path
                    print 'now check ',yesterday_file_path
                    #--log.log('now check file:%s'%(yesterday_file_path))
                    self.add_log('now check file:%s'%(yesterday_file_path))
                    #print svn.get_log(yesterday_file_path,yesterday_begin_rev,yesterday_end_rev)
                    all_change_log = svn.get_log(yesterday_file_path,1,yesterday_end_rev)
                    yesterday_change_log = svn.get_log(yesterday_file_path,yesterday_begin_rev,yesterday_end_rev)
                    if not all_change_log and not yesterday_change_log:
                        continue
                    is_pass_flag = 1 #--标记是否成功通过检查
                    for i in range(len(yesterday_change_log)):
                        #print "i==",yesterday_change_log[i]['revision'].number
                        print 'get log with revision:',yesterday_change_log[i]['revision'].number
                        #--log.log('get log with revision:%s'%(yesterday_change_log[i]['revision'].number))
                        self.add_log('get log with revision:%s'%(yesterday_change_log[i]['revision'].number))
                        the_new_rev,the_mid_rev,the_old_rev = self.choose_revision(target,all_change_log,i+len(all_change_log)-len(yesterday_change_log))


                        if the_new_rev != -1:
                            #print "choose rev=",the_new_rev,the_mid_rev,the_old_rev
                            print "found target revision ",the_new_rev,the_mid_rev,the_old_rev,",now compare diff"
                            #--log.log("found target revision %s,%s,%s,now compare diff"%(the_new_rev,the_mid_rev,the_old_rev))
                            self.add_log("found target revision %s,%s,%s,now compare diff"%(the_new_rev,the_mid_rev,the_old_rev))
                            diff_new_mid = svn.diff(yesterday_file_path,svn.get_revision_of(the_mid_rev),svn.get_revision_of(the_new_rev))
                            diff_mid_old = svn.diff(yesterday_file_path,svn.get_revision_of(the_old_rev),svn.get_revision_of(the_mid_rev))

                            diff_new_change = self.parse_diff(diff_new_mid)
                            diff_old_change = self.parse_diff(diff_mid_old)

                            if diff_new_change != None and diff_old_change != None:

                                for k in diff_new_change:
                                    if k in diff_old_change:
                                        if diff_new_change[k][1] == diff_old_change[k][0]:
                                            tmp_data={}
                                            tmp_data['file'] = yesterday_file_path
                                            tmp_data['author'] = svn.get_info_by_num(yesterday_file_path,the_new_rev).next().last_changed_author
                                            tmp_data['conflict_rev'] = [the_mid_rev,the_new_rev]
                                            is_pass_flag = 0
                                            log_msg = "Warnning:%s maybe conflict,author is %s,conflict revision are %s"%(tmp_data['file'],tmp_data['author'] ,tmp_data['conflict_rev'])
                                            print log_msg
                                            #log.err_log(tmp_data)
                                            self.add_log(log_msg)
                                            self.queue_dict['notify_queue'].put(log_msg)
                                            #notify.add(tmp_data)
                                            break
                                        #print "error",k,diff_new_change[k],diff_old_change[k]
                                #print k,diff_new_change[k]
                    if is_pass_flag == 1:
                        pass
                        #log.log('Exit now')
            else:
                    print "no changes in yesterday"
                    #--log.log("no changes in yesterday")
                    self.add_log("no changes in yesterday")
            #--发警报邮件
            #--notify.notify()
            #--log.log('Exit now')
            self.add_log('do check Exit now')

if __name__ == '__main__':
    '''
    log = Log.Log()
    cfg_file = r'D:\Program Files\Maxthon3\Bin\config.ini'
    config = AppConfig.AppConfig(cfg_file,'utf-8-sig')
    notify = Notify.Notify(cfg_file)
    target = r'https://test/' #--设置需要检查的根目录
    target_list = ['folder'] #--设置检查的子目录
    svn = SvnClient.SvnClient(target,'ww','11',True)
    svn.set_logger(log)

    #print svn.get_info_by_num(target,32810).next()['repos_root_URL']
    print "Running......"
    username = 'why323'
    #--允许进行diff的后缀名
    sufix = ['.xml','.lua',]
##    for child_path in target_list:
##        target = svn.catfile(child_path)
##        print "path=",target
    tmp_dict = svn.get_yesterday_begin_and_end_revision(target)
    if 'begin' in tmp_dict:
        yesterday_begin_rev = tmp_dict['begin']
        yesterday_end_rev = tmp_dict['end']
        #print '@'*10,yesterday_begin_rev,yesterday_end_rev
        print 'found revision:',yesterday_begin_rev,yesterday_end_rev
        log.log('found revision:%s,%s'%(yesterday_begin_rev,yesterday_end_rev))
        for yesterday_file_path in svn.changed_files(target,yesterday_begin_rev,yesterday_end_rev):
            #--过滤器
            if not file_filter(yesterday_file_path):
                print yesterday_file_path,'not allow'
                continue
            yesterday_file_path = '/'.join((target,yesterday_file_path))
            #yesterday_file_path = svn.catfile(yesterday_file_path)

            #print "yesterday_file_path=",yesterday_file_path
            print 'now check ',yesterday_file_path
            log.log('now check file:%s'%(yesterday_file_path))
            #print svn.get_log(yesterday_file_path,yesterday_begin_rev,yesterday_end_rev)
            all_change_log = svn.get_log(yesterday_file_path,1,yesterday_end_rev)
            yesterday_change_log = svn.get_log(yesterday_file_path,yesterday_begin_rev,yesterday_end_rev)
            if not all_change_log and not yesterday_change_log:
                continue
            is_pass_flag = 1 #--标记是否成功通过检查
            for i in range(len(yesterday_change_log)):
                #print "i==",yesterday_change_log[i]['revision'].number
                print 'get log with revision:',yesterday_change_log[i]['revision'].number
                log.log('get log with revision:%s'%(yesterday_change_log[i]['revision'].number))
                the_new_rev,the_mid_rev,the_old_rev = choose_revision(target,all_change_log,i+len(all_change_log)-len(yesterday_change_log))


                if the_new_rev != -1:
                    #print "choose rev=",the_new_rev,the_mid_rev,the_old_rev
                    print "found target revision ",the_new_rev,the_mid_rev,the_old_rev,",now compare diff"
                    log.log("found target revision %s,%s,%s,now compare diff"%(the_new_rev,the_mid_rev,the_old_rev))
                    diff_new_mid = svn.diff(yesterday_file_path,svn.get_revision_of(the_mid_rev),svn.get_revision_of(the_new_rev))
                    diff_mid_old = svn.diff(yesterday_file_path,svn.get_revision_of(the_old_rev),svn.get_revision_of(the_mid_rev))

                    diff_new_change = parse_diff(diff_new_mid)
                    diff_old_change = parse_diff(diff_mid_old)

                    if diff_new_change != None and diff_old_change != None:

                        for k in diff_new_change:
                            if k in diff_old_change:
                                if diff_new_change[k][1] == diff_old_change[k][0]:
                                    tmp_data={}
                                    tmp_data['file'] = yesterday_file_path
                                    tmp_data['author'] = svn.get_info_by_num(yesterday_file_path,the_new_rev).next().last_changed_author
                                    tmp_data['conflict_rev'] = [the_mid_rev,the_new_rev]
                                    is_pass_flag = 0
                                    log_msg = "Warnning:%s maybe conflict,author is %s,conflict revision are %s"%(tmp_data['file'],tmp_data['author'] ,tmp_data['conflict_rev'])
                                    print log_msg
                                    log.err_log(tmp_data)
                                    notify.add(tmp_data)
                                    break
                                #print "error",k,diff_new_change[k],diff_old_change[k]
                        #print k,diff_new_change[k]
            if is_pass_flag == 1:
                pass
                #log.log('Exit now')
    else:
            print "no changes in yesterday"
            log.log("no changes in yesterday")
    #--发警报邮件
    notify.notify()
    log.log('Exit now')

    print "@"*10,svn.count_diff(diff13)
    print '@'*10,svn.count_diff(diff23)
    if svn.count_diff(diff13)<=svn.count_diff(diff23):
        print "错误"
        #log.error_logger(dict)
    #    a = '11'
    #    a.startswith(@@)
    '''






